#pragma once
#include <functional>
#include "Epoll.h"
#include <memory>
#include <unistd.h>
#include <queue>
#include <map>
#include <atomic>
#include <mutex>
#include <sys/syscall.h>
#include <sys/eventfd.h>
#include <sys/timerfd.h>    //定时器头文件
#include "Connection.h"

class Epoll;
class Channel;
class Connection;
using spConnection = std::shared_ptr<Connection>;

//事件循环类
class EventLoop
{
private:
    int timetvl_;                           //闹钟时间间隔，单位:秒
    int timeout_;                           //Connectionm对象超时的时间，单位:秒
    std::unique_ptr<Epoll> ep_;          //每个事件循环只有一个Epoll
    std::function<void(EventLoop*)> epoll_TimeOut_CallBack_;    //epoll_wait()超时的回调函数
    pid_t threadID_;        //事件循环ID
    std::queue<std::function<void()>> taskQueue_;       //事件循环线程被eventfd唤醒后执行的任务队列
    std::mutex mutex_;                      //任务队列同步的互斥锁
    int wakeupfd_;                          //用于唤醒事件循环线程的eventfd
    std::unique_ptr<Channel> wakeChannel_;  //eventfd的Channel
    int timerfd_;                            //定时器fd
    std::unique_ptr <Channel> timeChannel_;  //定时器channel    
    bool mainloop_;                          //true-是主事件循环，false是从事件循环
    std::mutex mmutex_;                     //维护conns_的互斥锁 
    std::map<int, spConnection> conns_;     //存放运行在该事件循环上全部的Connection对象
    std::function<void(int)> timerCallBack_;   //删除TcpServer中超时的Connection对象，将被设置为TcpServer::removeconn()
    std::atomic_bool stop_;                 //初始化为false，用于停止事件循环
    //1.在事件循环中增加map<int, spConnect> conns_容器，存放运行在该事件循环上全部的Connection对象
    //2.如果闹钟时间到了，遍历conns_，判断每个Connection对象是否超时
    //3.如果超时了，从conns_中删除Connection对象
    //4.还需从TcpServer.conns_中删除Connection对象

public:
    EventLoop(bool isMainloop, int timetvl = 30, int timeout_ = 80);        //构造函数中创建Epoll对象ep_
    ~EventLoop();       //析构函数中销毁ep_

    void run();         //运行事件循环
    void stop();        //停止事件循环

    Epoll* ep();        //返回ep_
    void removeChannel(Channel *ch);        //把channel从红黑树上删除
    void set_epoll_TimeOut_CallBack(std::function<void(EventLoop*)> func);
    void setTimerCallBack(std::function<void(int)> func);   //将被设置为TcpServer::removeConn()

    bool isInLoopThread();  //判断当前线程是否为事件循环线程
    void queueInLoop(std::function<void()> func);    //把任务队列添加到队列中
    void wakeUp();          //用eventfd唤醒事件循环线程
    void handleWakeUp();    //事件循环被唤醒后执行的函数

    void handleTimer();     //闹钟响时执行的函数

    void newConnection(spConnection conn);  //把Connection对象保存在conns_中;
};